﻿using System;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Globalization;
using System.Reflection;

namespace JQuery.WebKit.WebCommon.Javascript
{
    [System.Diagnostics.DebuggerDisplay("{_value}")]
    [TypeConverter(typeof(JSHashTypeConverter))]
    public class JSHash
    {
        internal string _value;

        #region public JSHash(string s)
        /// <summary>
        /// Initializes a new instance of the <b>JSHash</b> class.
        /// </summary>
        /// <param name="s"></param>
        public JSHash(string s)
        {
            _value = s;
        }
        #endregion

        #region public static implicit operator JSHash(string s)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static implicit operator JSHash(string s)
        {
            return new JSHash(s);
        }
        #endregion

        #region public static explicit operator string(JSHash f)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        public static explicit operator string(JSHash f)
        {
            return f.ToJSString();
        }
        #endregion

        #region public override string ToString()
        /// <summary>
        /// Returns a <see cref="string"/> that represents the current <see cref="Web.Common.Javascript.JSHash"/>.
        /// </summary>
        /// <returns>A <see cref="string"/> that represents the current <see cref="Web.Common.Javascript.JSHash"/>.</returns>
        public override string ToString()
        {
            if (string.IsNullOrEmpty(_value))
            {
                return string.Empty;
            }
            string beginVal = _value.TrimStart().StartsWith("{") ? string.Empty : "{";
            string endVal = _value.TrimEnd().EndsWith("}") ? string.Empty : "}";
            return beginVal + _value.Trim() + endVal;
        }
        #endregion
    }

    public class JSHashTypeConverter : TypeConverter
    {
        #region public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="sourceType"></param>
        /// <returns></returns>
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string))
            {
                return true;
            }
            return base.CanConvertFrom(context, sourceType);
        }
        #endregion

        #region public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="destinationType"></param>
        /// <returns></returns>
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                return true;
            }
            //for aspx page parser
            if (destinationType == typeof(InstanceDescriptor))
            {
                return true;
            }
            return base.CanConvertTo(context, destinationType);
        }
        #endregion

        #region public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="culture"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            if (value is string)
            {
                JSHash hash = value as string;
                return hash;
            }
            return base.ConvertFrom(context, culture, value);
        }
        #endregion

        #region public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="culture"></param>
        /// <param name="value"></param>
        /// <param name="destinationType"></param>
        /// <returns></returns>
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (value is JSHash)
            {
                if (destinationType == typeof(string))
                {
                    value.ToJSString();
                }

                //for aspx page parser
                if (destinationType == typeof(InstanceDescriptor))
                {
                    JSHash hash = (JSHash)value;
                    ConstructorInfo constructor = typeof(JSHash).GetConstructor(new Type[] { typeof(string) });
                    InstanceDescriptor instance = new InstanceDescriptor(constructor, new object[] { hash._value });
                    return instance;
                }
            }
            return base.ConvertTo(context, culture, value, destinationType);

        }
        #endregion
    }
}
